﻿#pragma once
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/web/mime/multipart/Multipart.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "../dto/RecordDto.h"
#include "../dto/CountDto.h"
#include "../dto/RecordListDto.h"
#include "../vo/RecordVo.h"
#include "../service/EventRecordService.h"
#include "../AiBox.h"
#include "../util/TextUtil.h"
#include "../AiBox.h"

#include OATPP_CODEGEN_BEGIN(ApiController)

/**
 * 录像控制器
 */
class RecordController : public oatpp::web::server::api::ApiController {
public:
	RecordController(const std::shared_ptr<ObjectMapper>& objectMapper)
	: oatpp::web::server::api::ApiController(objectMapper) 
	{}

	/*
	* 开始录像
	*/
	ENDPOINT("GET", "/record/start", startRecord,
		HEADER(String, authorization, "Authorization"),
		QUERY(String, deviceId)) {

		// 返回操作结果
		auto result = SimpleDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取监视器
		AiMonitorPtr monitor = Box::get_mutable_instance().GetAiMonitor();
		if (!monitor)
		{
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取检测器
		DetectorPtr detector = monitor->Find(deviceId.getValue(""));
		if (!monitor)
		{
			result->description = "无效的设备编码!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 启动手动录像
		if (!detector->StartRecord())
		{
			result->description = "录像失败或正在录像中!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 返回操作结果
		result->error = 0;
		result->description = "success";
		return createDtoResponse(Status::CODE_200, result);
	}

	/*
	* 停止录像
	*/
	ENDPOINT("GET", "/record/stop", stopRecord,
		HEADER(String, authorization, "Authorization"),
		QUERY(String, deviceId)) {

		// 返回操作结果
		auto result = SimpleDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取监视器
		AiMonitorPtr monitor = Box::get_mutable_instance().GetAiMonitor();
		if (!monitor)
		{
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取检测器
		DetectorPtr detector = monitor->Find(deviceId.getValue(""));
		if (!monitor)
		{
			result->description = "无效的设备编码!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 停止手动录像
		detector->StopRecord();

		// 返回操作结果
		result->error = 0;
		result->description = "success";
		return createDtoResponse(Status::CODE_200, result);
	}

	/*
	* 开始抓拍
	*/
	ENDPOINT("GET", "/record/capture", startCapture,
		HEADER(String, authorization, "Authorization"),
		QUERY(String, deviceId)) {

		// 返回操作结果
		auto result = SimpleDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取监视器
		AiMonitorPtr monitor = Box::get_mutable_instance().GetAiMonitor();
		if (!monitor)
		{
			return createDtoResponse(Status::CODE_200, result);
		}

		// 获取检测器
		DetectorPtr detector = monitor->Find(deviceId.getValue(""));
		if (!monitor)
		{
			result->description = "无效的设备编码!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 启动手动抓拍
		if (!detector->StartCapture())
		{
			result->description = "设备未录像或抓拍失败!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 返回操作结果
		result->error = 0;
		result->description = "success";
		return createDtoResponse(Status::CODE_200, result);
	}

	/*
	* 手动录像预览
	*/
	ENDPOINT("GET", "/record/download", getRecordFile,
		QUERY(String, id))
	{
		EventRecordInfo recordInfo;
		recordInfo.SetId(id.getValue(""));

		EventRecordService recordService;
		if (!recordService.Find(recordInfo))
		{
			return createResponse(Status::CODE_404, "invalid id:" + recordInfo.GetId());
		}

		std::string path = recordInfo.GetPath();
		if (!FileUtil::Exists(path) || FileUtil::IsDir(path))
		{
			return ResponseFactory::createResponse(Status::CODE_404, "invalid path:" + path);
		}

		std::string content = FileUtil::Read(path);
		return createResponse(Status::CODE_200, content);
	}

	/*
	* 删除录像
	*/
	ENDPOINT("DELETE", "/record/delete", deleteRecord,
		HEADER(String, authorization, "Authorization"),
		QUERY(String, id)) {

		// 返回操作结果
		auto result = SimpleDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 录像信息
		EventRecordInfo record;
		record.SetId(id.getValue(""));

		// 删除录像
		EventRecordService recordService;
		if (recordService.Find(record))
		{
			if (!record.GetPath().empty())
			{
				Box::get_mutable_instance().GetFileClear()->AddFile(record.GetPath());
			}
			recordService.Delete(record);
		}

		// 返回操作结果
		result->error = 0;
		result->description = "success";
		result->value = record.GetId();
		return createDtoResponse(Status::CODE_200, result);
	}

	/*
	* 获取录像数量
	*/
	ENDPOINT("GET", "/record/count", getRecordCount,
		HEADER(String, authorization, "Authorization"),
		REQUEST(std::shared_ptr<IncomingRequest>, request)) {

		// 获取筛选参数
		std::string deviceId = request->getQueryParameter("deviceId").getValue("");
		std::string startTime = request->getQueryParameter("beginTime").getValue("");
		std::string endTime = request->getQueryParameter("endTime").getValue("");
		std::string upload = request->getQueryParameter("upload").getValue("");
		// 2024-04-06+00:00:00
		if (startTime.find("+") != -1)
		{
			startTime = TextUtil::get_mutable_instance().ReplaceAll(startTime, "+", " ");
		}
		if (endTime.find("+") != -1)
		{
			endTime = TextUtil::get_mutable_instance().ReplaceAll(endTime, "+", " ");
		}

		// 返回操作结果
		auto result = CountDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		if (startTime.empty() && endTime.empty())
		{
			result->description = "查询起止时间无效!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 查询录像数量
		EventRecordService recordService;
		int count = recordService.Count(deviceId, startTime, endTime, upload);

		// 返回操作结果
		result->error = 0;
		result->description = "success";
		result->value = count;
		return createDtoResponse(Status::CODE_200, result);
	}

	/**
	 * 查询录像列表
	 */
	ENDPOINT("GET", "/record/list", listRecord,
		HEADER(String, authorization, "Authorization"),
		QUERY(Int32, pageIndex),
		QUERY(Int32, pageSize),
		REQUEST(std::shared_ptr<IncomingRequest>, request)) {

		// 获取筛选参数
		std::string deviceId = request->getQueryParameter("deviceId").getValue("");
		std::string startTime = request->getQueryParameter("beginTime").getValue("");
		std::string endTime = request->getQueryParameter("endTime").getValue("");
		std::string upload = request->getQueryParameter("upload").getValue("");
		// 2024-04-06+00:00:00
		if (startTime.find("+") != -1)
		{
			startTime = TextUtil::get_mutable_instance().ReplaceAll(startTime, "+", " ");
		}
		if (endTime.find("+") != -1)
		{
			endTime = TextUtil::get_mutable_instance().ReplaceAll(endTime, "+", " ");
		}

		// 返回操作结果
		auto result = RecordListDto::createShared();
		result->error = -1;
		result->description = "服务器内部错误!";

		if (startTime.empty() && endTime.empty())
		{
			result->description = "查询起止时间无效!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 查找用户信息
		if (SystemConfig::get_mutable_instance().GetBoxConf().GetUser().GetToken() !=
			TextUtil::get_mutable_instance().GetToken(authorization.getValue("")))
		{
			result->description = "无效令牌!";
			return createDtoResponse(Status::CODE_200, result);
		}

		// 查询录像信息
		int index = (pageIndex.getValue(1) - 1) * pageSize.getValue(10);
		int size = pageSize.getValue(10);

		std::vector<EventRecordInfo> records;
		EventRecordService recordService;
		recordService.FindPage(index, size, deviceId, startTime, endTime, upload, records);

		// 初始化空列表
		oatpp::List<oatpp::Object<RecordVo>> items({});

		// 填充录像列表
		for (size_t index = 0; index < records.size(); ++index)
		{
			auto record = RecordVo::createShared();
			record->id = records[index].GetId();
			record->deviceId = records[index].GetDeviceId();
			record->deviceName = records[index].GetDeviceName();
			record->eventId = records[index].GetEventId();
			record->eventType = records[index].GetEventType();
			record->image = records[index].GetImage();
			record->startTime = records[index].GetStartTime().ToNormalString();
			record->stopTime = records[index].GetStopTime().ToNormalString();
			record->name = records[index].GetName();
			record->size = records[index].GetSize();
			record->duration = records[index].GetDuration();
			record->path = records[index].GetPath();
			record->url = records[index].GetUrl();
			record->createTime = records[index].GetCreateTime().ToNormalString();
			record->upload = records[index].GetUpload();
			record->uploadTime = records[index].GetUploadTime().ToNormalString();
			items->emplace(items->end(), record);
		}

		// 返回录像列表
		result->error = 0;
		result->description = "success";
		result->value = items;
		return createDtoResponse(Status::CODE_200, result);
	}
};

#include OATPP_CODEGEN_END(ApiController)